from __future__ import annotations
from math import floor

from base.ship_enum import ShipAttr
from base.observer_pattern import Observer


class Enhancement(Observer):
    def update(self, subject):
        self._level = subject.level

    enhancement_attrs = (ShipAttr.FP, ShipAttr.TRP, ShipAttr.AVI, ShipAttr.RLD)
    def __init__(self, max_limit: tuple[int,int,int,int],
                 *,
                 flag_set: bool = False,
                 flag_enable: bool = True,
                 **kwargs):
        """
        舰船强化信息, 强化信息有三组数值, 分别是最大强化上限, 当前强化上限和强化数值.
        最大强化上限是舰船100级时的强化上限, 每艘战舰有各自的数值.
        当前强化上限由最大强化上限和当前等级计算获得, 是当前等级强化数值的上限.
        强化数值是实际生效的强化数值.
        每组数值都有fp/trp/avi/rld四个数值, fp是炮击, trp是雷击, avi是航空, rld是装填.
        :param max_limit: 存有炮击/雷击/航空/装填四个属性强化最大上限的四元组;
        :param flag_set: 为假时, 通过计算获得当前最大强化数值, 如果未与状态实例关联, 默认为100级的最大强化数值;
            为真时, 可以通过 set_limit_value() 或 set_all_limit_value() 修改当前强化数值.
        :param flag_enable: 启用标志, 为假时, 强化值强制返回0, 实例内部保存的强化数值不变.
        :param kwargs: 可以设置强化数值, 约定使用以下键:
            fp: 炮击强化数值;
            trp: 雷击强化数值;
            avi: 航空强化数值;
            rld: 装填强化数值.
        """
        # 动态创建最大强化数值属性
        for i,v in enumerate(max_limit):
            setattr(self, f'_max_{self.enhancement_attrs[i].value}', v)
        self._level = 100
        self._flag_set = flag_set
        self._flag_enable = flag_enable
        # 动态创建强化数值属性
        for i in self.enhancement_attrs:
            setattr(self, f'_{i.value}', kwargs.get(f'{i.value}', 0))


    @property
    def flag_set(self) -> bool:
        """设置标志, 为True时使用设置的强化值, 为False时使用计算的强化值"""
        return self._flag_set

    @flag_set.setter
    def flag_set(self, value: bool):
        self._flag_set = value

    @property
    def flag_enable(self) -> bool:
        """启用标志, 是否启用强化, 为False时, 强化值强制返回0"""
        return self._flag_enable

    @flag_enable.setter
    def flag_enable(self, value: bool):
        self._flag_enable = value

    def set_limit_value(self, attr: ShipAttr, value: int) -> bool:
        """
        设置一个属性的最大强化上限
        :param attr: 要设置的属性
        :param value: 上限值
        :return: 是否设置成功
        """
        if attr not in self.enhancement_attrs:
            print("设定的属性不在可强化属性范围内")
            return False
        setattr(self, f'_max_{attr.value}', value)
        return True

    def set_all_limit_value(self, fp: int, trp: int, avi: int, rld: int):
        """
        设置所有强化属性的最大强化上限
        :param fp: 炮击
        :param trp: 雷击
        :param avi: 航空
        :param rld: 装填
        :return: 是否设置成功
        """
        setattr(self, '_max_fp', fp)
        setattr(self, '_max_trp', trp)
        setattr(self, '_max_avi', avi)
        setattr(self, '_max_rld', rld)

    def set_enhancement_value(self, attr: ShipAttr, value: int):
        """
        如果设置标志为True, 设置一个属性的强化值
        :param attr: 设置的属性
        :param value: 强化值
        :return: 是否设置成功
        """
        if attr not in self.enhancement_attrs:
            raise ValueError("设定的属性不在可强化属性范围内")
        setattr(self, f'_{attr.value}', max(0, min(value, self._get_cur_max(attr))))

    def set_all_enhancement_value(self, args:tuple[int,int,int,int]):
        """
        如果设置标志为True, 设置所有属性的强化值
        :param args: 包含炮击/雷击/航空/装填四个值的四元组
        :return: 是否设置成功
        """
        for i,j in enumerate(self.enhancement_attrs):
            setattr(self, f'_{j.value}', max(0, min(args[i], self._get_cur_max(ShipAttr.FP))))

    def _get_cur_max(self, attr: ShipAttr):
        """获取当前最大强化值"""
        if self._level is None:
            return None
        return floor((min(self._level, 100) / 100 * 0.7 + 0.3) * getattr(self, f'_max_{attr.value}'))

    def _get_result(self, attr: ShipAttr):
        """
        根据设置标志和启用标志返回强化值
        :param attr: 属性
        :return: 实际的强化数值
        """
        if self._flag_set:
            return getattr(self, f'_{attr.value}') if self._flag_enable else 0
        else:
            return self._get_cur_max(attr) if self._flag_enable else 0

    @property
    def fp(self):
        """炮击强化值"""
        return self._get_result(ShipAttr.FP)

    @property
    def trp(self):
        """雷击强化值"""
        return self._get_result(ShipAttr.TRP)

    @property
    def avi(self):
        """航空强化值"""
        return self._get_result(ShipAttr.AVI)

    @property
    def rld(self):
        """装填强化值"""
        return self._get_result(ShipAttr.RLD)
